package au.edu.unsw.editingtool.web;

/**
 * @author r.chen
 * 
 * Login Manager handle all login matters.
 * 
 */

import java.io.IOException;
import java.sql.SQLException;
import java.util.Hashtable;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import au.edu.unsw.editingtool.authentication.LDAP;
import au.edu.unsw.editingtool.db.DBAffiliation;
import au.edu.unsw.editingtool.db.DBUser;
import au.edu.unsw.editingtool.db.DBClaims;
import au.edu.unsw.editingtool.db.DBLogin;
import au.edu.unsw.editingtool.db.DBLoginpool;
import au.edu.unsw.editingtool.db.DBPublication;
import au.edu.unsw.editingtool.global.EditingToolException;
import au.edu.unsw.editingtool.global.EditingToolGlobalConstant;
import au.edu.unsw.editingtool.web.limited.ClaimRequest;
import au.edu.unsw.editingtool.web.limited.EditAttachment;
import au.edu.unsw.editingtool.web.limited.EditMetaData;

/**
 * Servlet implementation class LoginManager
 */
public class LoginManager extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private static final String FS = System.getProperty("file.separator");
	
	private String ServletContext = "";
	
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public LoginManager() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		this.doService(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		this.doService(request, response);
	}
	
	private boolean getLDAPAuthenticated(LDAP ldap, HttpServletRequest req) {
		
		String username = req.getParameter(EditingToolGlobalConstant.requestUsername);
		String password = req.getParameter(EditingToolGlobalConstant.requestPassword);
		if ((username == null) || (username.trim().length() < 0))
			return false;
		if ((password == null) || (password.trim().length() < 0))
			return false;
		
		ldap.setPropertyFile(ServletContext + EditingToolGlobalConstant.configFilePath);
		
		return ldap.authenticate(username, password);
	}
	
	private int needClaim(HttpServletRequest req) throws EditingToolException, ClassNotFoundException, SQLException {
		DBClaims claims = new DBClaims();
		return claims.CheckClaims(req.getParameter(EditingToolGlobalConstant.requestUsername), 
								  req.getParameter(EditingToolGlobalConstant.requestPid));
	}
/*
	private boolean existsUser(HttpServletRequest req) throws ClassNotFoundException, SQLException, EditingToolException {
		DBLogin login = new DBLogin();
		return login.userExists(req.getParameter(EditingToolGlobalConstant.requestUsername));
	}
*/
	private void addUser(Hashtable<String, String> userinfo, HttpServletRequest req) throws EditingToolException, ClassNotFoundException, SQLException {
		Hashtable<String, String> registerInfo = new Hashtable<String, String>();
		
		DBAffiliation affiliation = new DBAffiliation();
		String affiliationID = affiliation.addAffiliation(userinfo.get("ou"));
		
		DBLogin login = new DBLogin();
		DBUser user = new DBUser();
		String username = req.getParameter(EditingToolGlobalConstant.requestUsername);
		registerInfo.put("Username", username);
		registerInfo.put("Password", req.getParameter(EditingToolGlobalConstant.requestPassword));
		registerInfo.put("Affiliation", affiliationID);
		registerInfo.put("Note", "User add after passed dhcp.");
		
		if (req.getParameter(EditingToolGlobalConstant.requestCommand).equals(EditingToolGlobalConstant.commandReview))
			login.addReviewer(registerInfo);
		else 
			login.addAuthor(registerInfo);
		
		registerInfo.clear();
		registerInfo.put("UserID", username);
		registerInfo.put("LastName", userinfo.get("sn"));
		registerInfo.put("OtherNames", userinfo.get("givenName"));
		registerInfo.put("Title", userinfo.get("personalTitle"));
		registerInfo.put("Email", (userinfo.get("mailForwardingAddress") == null) ? 
								   userinfo.get("mail"):
								   userinfo.get("mailForwardingAddress"));
		user.addUser(registerInfo);
	}
	
	// Need to think about the filter
	private void stepToTheNext(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		if (req.getParameter(EditingToolGlobalConstant.requestCommand).equals(EditingToolGlobalConstant.commandEdit)) {
			EditMetaData servlet = new EditMetaData();
			servlet.service(req, res);
		} else {
			EditAttachment servlet = new EditAttachment();
			servlet.service(req, res);
		}
	}
	
	// Need to think about the filter
	private void stepToClaimPage(HttpServletRequest req, HttpServletResponse res, boolean claimed) throws ServletException, IOException {
		req.setAttribute(EditingToolGlobalConstant.claimRequested, claimed);
		ClaimRequest servlet = new ClaimRequest();
		servlet.service(req, res);
	}

	private void startNewSession(HttpServletRequest req) throws EditingToolException, SQLException, ClassNotFoundException {
		String username = req.getParameter(EditingToolGlobalConstant.requestUsername);
		
		DBLoginpool loginPool = new DBLoginpool();		
		Hashtable<String, String> record = new Hashtable<String, String>();
		
		record.put("User", username);
		record.put("SessionID", req.getSession().getId());
		loginPool.addRecord(record);
		
		record.clear();
		// You also have to store the pid in the pidTable
		DBPublication dbPublication = new DBPublication();

		record.put("Publication", req.getParameter(EditingToolGlobalConstant.requestPid));
		dbPublication.addPublication(record);
		
		req.setAttribute(EditingToolGlobalConstant.sessionAttrUsername, username);
		req.setAttribute(EditingToolGlobalConstant.sessionAttrLid, loginPool.getReturnKey());
	}
	
	protected void doService(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		ServletContext = getServletContext().getRealPath("") + FS;
		LDAP ldap = new LDAP();
		boolean valid = this.getLDAPAuthenticated(ldap, req);
		
		if (!valid) {
			 res.sendRedirect("login.jsp?ctrl=error");
		} else {
			// check this user link to the publication.
			try {
				this.addUser(ldap.getAttributes(), req);
				this.startNewSession(req);
			} catch (Exception e) {
				e.printStackTrace();
			}
			try {
				switch (this.needClaim(req)) {
					case 0: // go Edit
						this.stepToTheNext(req, res);
					case 1:	// requested
						this.stepToClaimPage(req, res, true);
					case 2: // claim step
						this.stepToClaimPage(req, res, false);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

}
